package com.polar.idea.agent;

import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.cert.X509v3CertificateBuilder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
import org.bouncycastle.pkcs.PKCS10CertificationRequest;
import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequestBuilder;

import javax.security.auth.x500.X500Principal;
import java.io.*;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.*;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.Base64;
import java.util.Date;

/**
 * @author GuiBinWu
 * @Date 2024/10/28 下午 03:40
 */
public class CertificateMain {

    public static void main(String[] args) throws Exception {
        String path = "E:\\Idea\\idea-definded-agent\\src\\main\\resources\\keys\\";
        RSAPrivateKey rsaPrivateKey = RSAEncrypt.loadPrivateKeyByStr(
                RSAEncrypt.loadPrivateKeyByFile(path)
        );
        RSAPublicKey rsaPublicKey = RSAEncrypt.loadPublicKeyByStr(
                RSAEncrypt.loadPublicKeyByFile(path)
        );
        KeyPair keyPair = new KeyPair(rsaPublicKey, rsaPrivateKey);
        CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
        X509Certificate x509Certificate = (X509Certificate) certificateFactory.generateCertificate(
                Files.newInputStream(Paths.get(path + "cert.cer")));
//        String licensePart = "{\"licenseId\":\"CrazyThursdayVMEFIFTY\",\"licenseeName\":\"Mvp-Agent-Pock-Idea\",\"assigneeName\":\"\",\"assigneeEmail\":\"\",\"licenseRestriction\":\"\",\"checkConcurrentUse\":false,\"products\":[{\"code\":\"PCWMP\",\"fallbackDate\":\"2036-09-14\",\"paidUpTo\":\"2036-09-14\",\"extended\":true},{\"code\":\"PSI\",\"fallbackDate\":\"2026-09-14\",\"paidUpTo\":\"2026-09-14\",\"extended\":true},{\"code\":\"WS\",\"fallbackDate\":\"2026-09-14\",\"paidUpTo\":\"2026-09-14\",\"extended\":false}],\"metadata\":\"0120230914PSAX000005\",\"hash\":\"TRIAL:-1920204289\",\"gracePeriodDays\":7,\"autoProlongated\":false,\"isAutoProlongated\":false}";
        String licensePart = "{\"licenseId\":\"CrazyThursdayVmeFifty\",\"licenseeName\":\"永久激活 KFC V50\",\"assigneeName\":\"\",\"assigneeEmail\":\"\",\"licenseRestriction\":\"\",\"checkConcurrentUse\":false,\"products\":[{\"code\":\"DPN\",\"paidUpTo\":\"2028-02-04\",\"extended\":false},{\"code\":\"DB\",\"paidUpTo\":\"2028-02-04\",\"extended\":false},{\"code\":\"PS\",\"paidUpTo\":\"2028-02-04\",\"extended\":false},{\"code\":\"II\",\"paidUpTo\":\"2028-02-04\",\"extended\":false},{\"code\":\"RSC\",\"paidUpTo\":\"2028-02-04\",\"extended\":true},{\"code\":\"GO\",\"paidUpTo\":\"2028-02-04\",\"extended\":false},{\"code\":\"DM\",\"paidUpTo\":\"2028-02-04\",\"extended\":false},{\"code\":\"RSF\",\"paidUpTo\":\"2028-02-04\",\"extended\":true},{\"code\":\"DS\",\"paidUpTo\":\"2028-02-04\",\"extended\":false},{\"code\":\"PC\",\"paidUpTo\":\"2028-02-04\",\"extended\":false},{\"code\":\"RC\",\"paidUpTo\":\"2028-02-04\",\"extended\":false},{\"code\":\"CL\",\"paidUpTo\":\"2028-02-04\",\"extended\":false},{\"code\":\"WS\",\"paidUpTo\":\"2028-02-04\",\"extended\":false},{\"code\":\"RD\",\"paidUpTo\":\"2028-02-04\",\"extended\":false},{\"code\":\"RS0\",\"paidUpTo\":\"2028-02-04\",\"extended\":false},{\"code\":\"RM\",\"paidUpTo\":\"2028-02-04\",\"extended\":false},{\"code\":\"AC\",\"paidUpTo\":\"2028-02-04\",\"extended\":false},{\"code\":\"RSV\",\"paidUpTo\":\"2028-02-04\",\"extended\":true},{\"code\":\"DC\",\"paidUpTo\":\"2028-02-04\",\"extended\":false},{\"code\":\"RSU\",\"paidUpTo\":\"2028-02-04\",\"extended\":false},{\"code\":\"DP\",\"paidUpTo\":\"2028-02-04\",\"extended\":true},{\"code\":\"PDB\",\"paidUpTo\":\"2028-02-04\",\"extended\":true},{\"code\":\"PWS\",\"paidUpTo\":\"2028-02-04\",\"extended\":true},{\"code\":\"PSI\",\"paidUpTo\":\"2028-02-04\",\"extended\":true},{\"code\":\"PPS\",\"paidUpTo\":\"2028-02-04\",\"extended\":true},{\"code\":\"PCWMP\",\"paidUpTo\":\"2028-02-04\",\"extended\":true},{\"code\":\"PGO\",\"paidUpTo\":\"2028-02-04\",\"extended\":true},{\"code\":\"PPC\",\"paidUpTo\":\"2028-02-04\",\"extended\":true},{\"code\":\"PRB\",\"paidUpTo\":\"2028-02-04\",\"extended\":true},{\"code\":\"PSW\",\"paidUpTo\":\"2028-02-04\",\"extended\":true},{\"code\":\"RS\",\"paidUpTo\":\"2028-02-04\",\"extended\":true},{\"code\":\"PGITLAB\",\"paidUpTo\":\"2028-02-04\",\"extended\":true}],\"metadata\":\"0120220105PPAM000005\",\"hash\":\"29693627/0:-2069228347\",\"gracePeriodDays\":7,\"autoProlongated\":false,\"isAutoProlongated\":false}";
        String licenseId = "CrazyThursdayVMEFIFTY";
        byte[] licensePartBytes = licensePart.getBytes(StandardCharsets.UTF_8);
        String licensePartBase64 = Base64.getEncoder().encodeToString(licensePartBytes);
        PrivateKey privateKey = keyPair.getPrivate();
        Signature signature = Signature.getInstance("SHA1withRSA");
        signature.initSign(privateKey);
        signature.update(licensePartBytes);
        byte[] signatureBytes = signature.sign();

        String sigResultsBase64 = Base64.getEncoder().encodeToString(signatureBytes);
//        verify
        Signature verifySignature = Signature.getInstance("SHA1withRSA");
        verifySignature.initVerify(x509Certificate.getPublicKey());
        verifySignature.update(Base64.getDecoder().decode(licensePartBase64));
        boolean verify = verifySignature.verify(Base64.getDecoder().decode(sigResultsBase64));
        System.out.println(verify);


        // Combine results as needed
        String result = licenseId + "-" + licensePartBase64 + "-" + sigResultsBase64 + "-" + Base64.getEncoder()
                .encodeToString(x509Certificate.getEncoded());
        System.out.println(result);
    }

    public static String loadPublicKeyByFile(String path) throws Exception {
        try {
            BufferedReader br = new BufferedReader(new FileReader(path
                    + "/publicKey.keystore"));
            String readLine = null;
            StringBuilder sb = new StringBuilder();
            while ((readLine = br.readLine()) != null) {
                sb.append(readLine);
            }
            br.close();
            return sb.toString();
        } catch (IOException e) {
            throw new Exception("公钥数据流读取错误");
        } catch (NullPointerException e) {
            throw new Exception("公钥输入流为空");
        }
    }





    public static KeyPair generateKeys() throws NoSuchAlgorithmException {
        try {
            // 创建一个密钥对生成器
            KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
            // 设置密钥大小
            keyGen.initialize(2048);
            // 生成密钥对
            KeyPair keyPair = keyGen.generateKeyPair();
            PrivateKey privateKey = keyPair.getPrivate();
            PublicKey publicKey = keyPair.getPublic();
            // 输出密钥
            System.out.println("Private Key: " + privateKey.toString());
            System.out.println("Public Key: " + publicKey.toString());
            try {
                // 得到公钥字符串
                String publicKeyString = Base64.getEncoder().encodeToString(publicKey.getEncoded());
                // 得到私钥字符串
                String privateKeyString = Base64.getEncoder().encodeToString(privateKey.getEncoded());
                // 将密钥对写入到文件
                FileWriter pubfw = new FileWriter("E:\\Idea\\idea-definded-agent\\src\\main\\resources\\" + "publicKey.keystore");
                FileWriter prifw = new FileWriter("E:\\Idea\\idea-definded-agent\\src\\main\\resources\\" + "privateKey.keystore");
                BufferedWriter pubbw = new BufferedWriter(pubfw);
                BufferedWriter pribw = new BufferedWriter(prifw);
                pubbw.write(publicKeyString);
                pribw.write(privateKeyString);
                pubbw.flush();
                pubbw.close();
                pubfw.close();
                pribw.flush();
                pribw.close();
                prifw.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return keyPair;
        } catch (NoSuchAlgorithmException e) {
            throw e;
        }
    }
}
